package org.example.analysis.service.analyzer;

import lombok.extern.slf4j.Slf4j;
import org.example.analysis.model.ComplexityLevel;
import org.example.analysis.model.ClassComplexity;
import org.example.analysis.model.MethodComplexity;
import org.example.analysis.model.entity.JavaClassInfo;
import org.example.analysis.model.entity.JavaMethodInfo;
import org.example.analysis.service.MethodComplexityAnalyzer;
import org.example.analysis.service.dataobj.ClassDataObject;
import org.example.analysis.service.dataobj.MethodDataObject;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类复杂度分析器
 */
@Slf4j
public class ClassComplexityAnalyzer {
    
    private final MethodComplexityAnalyzer methodComplexityAnalyzer;
    private final Map<String, ClassComplexity> complexityCache = new HashMap<>();
    
    public ClassComplexityAnalyzer() {
        this.methodComplexityAnalyzer = new MethodComplexityAnalyzer();
    }
    
    /**
     * 分析类的复杂度
     */
    public ClassComplexity analyze(List<ClassDataObject> allClasses, ClassDataObject classInfo) {
        if (classInfo == null) return null;
        log.info("分析类复杂度: {}", classInfo.getClassName());
        // 生成类的唯一标识
        String classKey = generateClassKey(classInfo);
        
        // 如果已经分析过，直接返回缓存结果
        if (complexityCache.containsKey(classKey)) {
            return complexityCache.get(classKey);
        }
        
        try {
            // 创建复杂度对象
            ClassComplexity complexity = new ClassComplexity();
            complexity.setProjectName(classInfo.getProjectName())
                     .setPackageName(classInfo.getPackageName())
                     .setClassName(classInfo.getClassName());
            
            // 1. 基本指标
            complexity.setTotalLinesOfCode(calculateTotalLinesOfCode(classInfo));
            complexity.setMethodCount(classInfo.getMethods().size());
            complexity.setFieldCount(classInfo.getFields().size());
            complexity.setInnerClassCount(calculateInnerClassCount(classInfo));
            complexity.setInterfaceCount(classInfo.getInterfaces().size());
            complexity.setInheritanceDepth(calculateInheritanceDepth(allClasses, classInfo));
            
            // 2. 分析所有方法的复杂度
            List<MethodComplexity> methodComplexities = analyzeMethodComplexities(allClasses, classInfo);
            
            // 3. 计算方法相关指标
            calculateMethodMetrics(complexity, methodComplexities);
            
            // 4. 计算依赖相关指标
            calculateDependencyMetrics(allClasses, complexity, classInfo);
            
            // 5. 计算公共方法比例
            calculatePublicMethodRatio(complexity, classInfo);
            
            // 6. 计算复杂度得分和等级
            calculateComplexityScore(complexity);
            
            // 7. 生成改进建议
            generateImprovementSuggestions(complexity);
            
            // 8. 设置时间相关字段
            complexity.setLastAnalysisTime(new Date())
                     .setCreatedAt(new Date())
                     .setRefreshable(true);
            
            // 缓存分析结果
            complexityCache.put(classKey, complexity);
            return complexity;
            
        } catch (Exception e) {
            log.error("分析类复杂度失败: {}", classInfo.getClassName(), e);
            return null;
        }
    }
    
    /**
     * 生成类的唯一标识
     */
    private String generateClassKey(ClassDataObject classInfo) {
        return String.format("%s.%s",
            classInfo.getPackageName(),
            classInfo.getClassName());
    }
    
    /**
     * 计算总代码行数
     */
    private int calculateTotalLinesOfCode(ClassDataObject classInfo) {
        return classInfo.getMethods().stream()
                .mapToInt(MethodDataObject::getCodeLines)
                .sum();
    }
    
    /**
     * 计算内部类数量
     */
    private int calculateInnerClassCount(ClassDataObject classInfo) {
        return (int) classInfo.getInnerClasses().stream()
                .filter(Objects::nonNull)
                .count();
    }
    
    /**
     * 计算继承深度
     */
    private int calculateInheritanceDepth(List<ClassDataObject> allClasses, ClassDataObject classInfo) {
        int depth = 0;
        String currentSuperClass = classInfo.getSuperClass();
        
        while (currentSuperClass != null && !currentSuperClass.equals("java.lang.Object")) {
            depth++;
            // 查找父类
            final String searchClass = currentSuperClass;
            Optional<ClassDataObject> parentClass = allClasses.stream()
                    .filter(cls -> cls.getClassName().equals(searchClass))
                    .findFirst();
            
            if (parentClass.isPresent()) {
                currentSuperClass = parentClass.get().getSuperClass();
            } else {
                // 如果父类不在分析范围内，就停止计算
                break;
            }
        }
        
        return depth;
    }
    
    /**
     * 分析所有方法的复杂度
     */
    private List<MethodComplexity> analyzeMethodComplexities(List<ClassDataObject> allClasses, ClassDataObject classInfo) {
        return classInfo.getMethods().stream()
                .map(method -> methodComplexityAnalyzer.analyze(allClasses, method, classInfo))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
    
    /**
     * 计算方法相关指标
     */
    private void calculateMethodMetrics(ClassComplexity complexity, List<MethodComplexity> methodComplexities) {
        // 计算方法平均复杂度
        double avgComplexity = methodComplexities.stream()
                .filter(m -> Objects.nonNull(m.getComplexityScore()))
                .mapToInt(MethodComplexity::getComplexityScore)
                .average()
                .orElse(0.0);
        complexity.setAverageMethodComplexity(avgComplexity);
        
        // 计算高复杂度方法数量
        int highComplexityCount = (int) methodComplexities.stream()
                .filter(m->m.getComplexityScore() != null)
                .filter(m -> m.getComplexityScore() > 8)
                .count();
        complexity.setHighComplexityMethodCount(highComplexityCount);
    }
    
    /**
     * 计算依赖相关指标
     */
    private void calculateDependencyMetrics(List<ClassDataObject> allClasses, ClassComplexity complexity, ClassDataObject classInfo) {
        // 计算类的依赖数量
        Set<String> dependencies = new HashSet<>();
        classInfo.getMethods().forEach(method -> {
            // 添加方法参数类型
            method.getParameters().forEach(param -> dependencies.add(param.getParameterType()));
            // 添加方法返回类型
            dependencies.add(method.getReturnType());
            // 添加方法中使用的类型（这需要通过AST分析，这里简化处理）
        });
        // 移除基本类型和java.lang包下的类
        dependencies.removeIf(dep -> dep == null || dep.startsWith("java.lang.") || 
                isBasicType(dep) || dep.equals(classInfo.getClassName()));
        complexity.setDependencyCount(dependencies.size());
        
        // 计算被依赖数量
        int beingDependedCount = (int) allClasses.stream()
                .filter(cls -> !cls.getClassName().equals(classInfo.getClassName()))
                .flatMap(cls -> cls.getMethods().stream())
                .filter(method -> {
                    // 检查方法参数和返回值是否引用了当前类
                    boolean usedInParams = method.getParameters().stream()
                            .anyMatch(param -> param.getParameterType().equals(classInfo.getClassName()));
                    boolean usedInReturn = method.getReturnType().equals(classInfo.getClassName());
                    return usedInParams || usedInReturn;
                })
                .count();
        complexity.setBeingDependedCount(beingDependedCount);
    }
    
    /**
     * 计算公共方法比例
     */
    private void calculatePublicMethodRatio(ClassComplexity complexity, ClassDataObject classInfo) {
        int totalMethods = classInfo.getMethods().size();
        if (totalMethods == 0) {
            complexity.setPublicMethodRatio(0.0);
            return;
        }
        
        long publicMethods = classInfo.getMethods().stream()
                .filter(method -> "public".equals(method.getAccessModifier()))
                .count();
        
        complexity.setPublicMethodRatio((double) publicMethods / totalMethods);
    }
    
    /**
     * 计算复杂度得分
     */
    private void calculateComplexityScore(ClassComplexity complexity) {
        int score = 0;
        
        // 1. 代码行数评分
        if (complexity.getTotalLinesOfCode() > 1000) score += 4;
        else if (complexity.getTotalLinesOfCode() > 500) score += 3;
        else if (complexity.getTotalLinesOfCode() > 200) score += 2;
        else if (complexity.getTotalLinesOfCode() > 100) score += 1;
        
        // 2. 方法数量评分
        if (complexity.getMethodCount() > 30) score += 4;
        else if (complexity.getMethodCount() > 20) score += 3;
        else if (complexity.getMethodCount() > 10) score += 2;
        else if (complexity.getMethodCount() > 5) score += 1;
        
        // 3. 属性数量评分
        if (complexity.getFieldCount() > 20) score += 3;
        else if (complexity.getFieldCount() > 10) score += 2;
        else if (complexity.getFieldCount() > 5) score += 1;
        
        // 4. 内部类数量评分
        if (complexity.getInnerClassCount() > 5) score += 3;
        else if (complexity.getInnerClassCount() > 3) score += 2;
        else if (complexity.getInnerClassCount() > 1) score += 1;
        
        // 5. 接口数量评分
        if (complexity.getInterfaceCount() > 5) score += 3;
        else if (complexity.getInterfaceCount() > 3) score += 2;
        else if (complexity.getInterfaceCount() > 1) score += 1;
        
        // 6. 继承深度评分
        if (complexity.getInheritanceDepth() > 5) score += 4;
        else if (complexity.getInheritanceDepth() > 3) score += 2;
        else if (complexity.getInheritanceDepth() > 1) score += 1;
        
        // 7. 方法平均复杂度评分
        if (complexity.getAverageMethodComplexity() > 8) score += 4;
        else if (complexity.getAverageMethodComplexity() > 6) score += 3;
        else if (complexity.getAverageMethodComplexity() > 4) score += 2;
        else if (complexity.getAverageMethodComplexity() > 2) score += 1;
        
        // 8. 高复杂度方法比例评分
        double highComplexityRatio = (double) complexity.getHighComplexityMethodCount() / complexity.getMethodCount();
        if (highComplexityRatio > 0.3) score += 4;
        else if (highComplexityRatio > 0.2) score += 3;
        else if (highComplexityRatio > 0.1) score += 2;
        else if (highComplexityRatio > 0.05) score += 1;
        
        // 9. 依赖数量评分
        if (complexity.getDependencyCount() > 20) score += 4;
        else if (complexity.getDependencyCount() > 15) score += 3;
        else if (complexity.getDependencyCount() > 10) score += 2;
        else if (complexity.getDependencyCount() > 5) score += 1;
        
        // 10. 公共方法比例评分（过高的公共方法比例可能违反封装原则）
        if (complexity.getPublicMethodRatio() > 0.8) score += 3;
        else if (complexity.getPublicMethodRatio() > 0.6) score += 2;
        else if (complexity.getPublicMethodRatio() > 0.4) score += 1;
        
        complexity.setComplexityScore(score);
        
        // 设置复杂度等级
        if (score >= 20) complexity.setLevel(ComplexityLevel.VERY_HIGH);
        else if (score >= 15) complexity.setLevel(ComplexityLevel.HIGH);
        else if (score >= 10) complexity.setLevel(ComplexityLevel.MEDIUM);
        else complexity.setLevel(ComplexityLevel.LOW);
    }
    
    /**
     * 生成改进建议
     */
    private void generateImprovementSuggestions(ClassComplexity complexity) {
        StringBuilder suggestions = new StringBuilder();
        
        // 1. 基于代码行数的建议
        if (complexity.getTotalLinesOfCode() > 500) {
            suggestions.append("- 建议将大类拆分为多个较小的类，每个类专注于单一职责\n");
        }
        
        // 2. 基于方法数量的建议
        if (complexity.getMethodCount() > 20) {
            suggestions.append("- 考虑将部分方法提取到新的类中，或使用组合模式拆分功能\n");
        }
        
        // 3. 基于属性数量的建议
        if (complexity.getFieldCount() > 10) {
            suggestions.append("- 属性数量过多，建议:\n")
                      .append("  1. 将相关的属性封装为新的类\n")
                      .append("  2. 使用Builder模式管理属性初始化\n");
        }
        
        // 4. 基于继承深度的建议
        if (complexity.getInheritanceDepth() > 3) {
            suggestions.append("- 继承层次过深，建议:\n")
                      .append("  1. 考虑使用组合替代继承\n")
                      .append("  2. 重构继承体系，减少层级数量\n");
        }
        
        // 5. 基于方法复杂度的建议
        if (complexity.getAverageMethodComplexity() > 6) {
            suggestions.append("- 方法平均复杂度较高，建议:\n")
                      .append("  1. 将复杂方法拆分为多个简单方法\n")
                      .append("  2. 使用策略模式分离复杂的业务逻辑\n");
        }
        
        // 6. 基于依赖数量的建议
        if (complexity.getDependencyCount() > 15) {
            suggestions.append("- 类的依赖过多，建议:\n")
                      .append("  1. 引入外观模式统一管理外部依赖\n")
                      .append("  2. 使用依赖注入管理对象创建\n")
                      .append("  3. 考虑是否违反了单一职责原则\n");
        }
        
        // 7. 基于公共方法比例的建议
        if (complexity.getPublicMethodRatio() > 0.7) {
            suggestions.append("- 公共方法比例过高，建议:\n")
                      .append("  1. 检查是否违反了封装原则\n")
                      .append("  2. 将部分公共方法改为私有或包级别访问\n");
        }
        
        // 8. 基于内部类的建议
        if (complexity.getInnerClassCount() > 3) {
            suggestions.append("- 内部类数量过多，建议:\n")
                      .append("  1. 将独立的内部类提取为顶级类\n")
                      .append("  2. 检查是否可以使用设计模式优化结构\n");
        }
        
        complexity.setImprovementSuggestions(suggestions.toString());
    }
    
    /**
     * 判断是否是基本类型
     */
    private boolean isBasicType(String type) {
        return type != null && (
            type.equals("int") || type.equals("long") || type.equals("float") || 
            type.equals("double") || type.equals("boolean") || type.equals("char") || 
            type.equals("byte") || type.equals("short") || type.equals("void")
        );
    }
} 